//package com.dy.high.readt;
//
//import org.junit.jupiter.api.Test;
//import sun.rmi.runtime.Log;
//
//import java.io.*;
//import java.util.*;
//
///**
// * @author huangdeyao
// * @date 2019/8/23 21:31
// */
//
//public class ReadTxtTest4 {
//
//
//    /**
//     * 记录集合数据
//     */
////    private static List<String> endData = new ArrayList<>();
//    /**
//     * 头数据 这里使用LinkedHashMap 保证输入跟输出的顺序保持一致
//     */
//    private static Map<String, String> titleMap = new LinkedHashMap<>();
//    /**
//     * 定义一个与头信息一样的map 方便后面数据跟头数据的顺序保持一致
//     */
//    private static Map<String, String> contextMap = new LinkedHashMap<>();
//    /**
//     * 存一份缓存数据map，该数据始终是数据写入到txt之前 的一条缓存数据
//     */
//    private Map<String, String> swapMap = new LinkedHashMap<>();
//    /**
//     * 基准时间
//     */
//    private long baseTime = 0;
//    /**
//     * 执行次数, 此处理解为游标更合适
//     */
//    private long runTimes = 0;
//    /**
//     * 当前正确的游标值
//     */
//    private long correct = 0;
//    /**
//     * 数据结束时 最后写入txt数据的时间戳 目的是处理缓存区中的数据是否写入到TXT文件中
//     */
//    private String overTime = "";
//
//    /**
//     * 测试程序入口
//     */
//    @Test
//    public void dealData() throws IOException {
//        // 开时时间
//        long bTime1 = System.currentTimeMillis();
//        /**
//         * 主程序
//         */
//        readTxt();
//        //关闭总计时
//        long eTime1 = System.currentTimeMillis();
//        //输出
//        System.out.println("插入数据共耗时：" + (eTime1 - bTime1));
//    }
//
//    /**
//     * 读数据
//     */
//    private void readTxt() throws IOException {
//
//        try {
//            BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream(new File("C://data_input//in_data.txt")), "UTF-8"));
//            String lineTxt = null;
//            while ((lineTxt = br.readLine()) != null) {
//                // 数据切割
//                String[] strings = lineTxt.split(",");
//                // 第一行头数据截取后长度大于3，其他数据集合长度截取后长度为3，此处使用该条件判断当前行数是否为头
//                if (strings.length > 3) {
//                    // 装载头信息
//                    titleHandle(strings);
//                } else {
//                    // 数据处理逻辑
//                    contextHandle(strings);
//                }
//            }
//            br.close();
//            // 判断缓存区是否有数据遗留 而且没有写入txt
//            if (!overTime.equals(swapMap.get("timestamp"))) {
//                swapMap.put("timestamp", String.valueOf(correct));
//                addData(swapMap);
//            }
//            // 处理第N条数据，程序逻辑处理n - 1 条数据，所以会遗留下来一条
//            if (contextMap.size() > 0) {
//                handleEndData(contextMap);
//            }
//            bw.close();
//        } catch (Exception e) {
//            System.err.println("read errors :" + e);
//        } finally {
//            bw.close();
//        }
//    }
//
//    /**
//     * 处理最后遗留下的数据,缓存区的数据和最后一条未执行判断的数据
//     */
//    private void handleEndData(Map<String, String> map) {
//        long timestamp = Long.valueOf(map.get("timestamp"));
//        correct = baseTime + runTimes * 20;
//        if (correct == timestamp) {
//            addData(map);
//        } else if (correct > timestamp) {
//            map.put("timestamp", String.valueOf(correct));
//            addData(map);
//        } else {
//            handleEndData(contextMap);
//        }
//
//    }
//
//    /**
//     * 数据处理逻辑
//     *
//     * @param strings 读取的当前行数据
//     */
//    private void contextHandle(String[] strings) {
//        // 判断是否有时间戳 每次判断有时间戳的时候初始化一次
//        if (null != strings[0] && !"".equals(strings[0])) {
//            // 第一次执行 读取第一行代码
//            // 放入时间戳 第一行基准时间点
//            if ("0".equals(contextMap.get("timestamp"))) {
//                // 放入时间戳
//                contextMap.put("timestamp", strings[0]);
//                baseTime = Long.valueOf(strings[0]);
//            } else {
//                // 此处 第n 执行  执行的数据为第 n-1 次数据
//                // 此处判断第一次执行代码
//                if (runTimes == 0) {
//                    // 写入第一条数据 第一条数据为时间基准点，不需要判断是否有多条数据
//                    addData();
//                } else {
//                    /**
//                     * 后续数据处理
//                     */
//                    handleCile(strings);
//                }
//                // n-1 数据装载完成后 放入第 n 次的时间点，并且组装第n次的contextMap 也就是当前读取的时间点数据
//                contextMap.put("timestamp", strings[0]);
//            }
//        }
//        // 查找当前数据 相对于头数据的属性
//        handleMap(strings);
//    }
//
//    /**
//     * 处理 数据
//     *
//     * @param strings
//     */
//    private void handleCile(String[] strings) {
//        // 第n - 1的时间
//        long timestamp = Long.valueOf(contextMap.get("timestamp"));
//        // 此时的时间节点应该是 基准时间  + 执行次数 * 20
//        correct = baseTime + runTimes * 20;
//        // 如果相等，说明当前时间节点的数据正常, 直接赋值写入，执行次数加一，表示下一个时间节点
//        if (correct == timestamp) {
//            addData();
//        } else {
//            /**
//             * 如果n - 1的时间大于correct， 说明correct 与 timestamp中间缺少数据
//             */
//            long willBeInputTime = Long.valueOf(strings[0]);
//            if (correct < timestamp) {
//                // 将要导入的数据时间戳大于当前游标时间 更新时间戳然后保存保存timestamp 中的数据（n-1）
//                if (correct < willBeInputTime) {
//                    // 小于游标时间 而下一个数据大于游标的数据
//                    swapMap.put("timestamp", String.valueOf(correct));
//                    addData(swapMap);
//                }
//                // 递归一次 当前参数值
//                handleCile(strings);
//            } else {
//                // 主要目的是获取n - 2的数据 否则会出现，小于游标时间，而下一个数据大于游标的数据，全局map中会混入n-1 的值
//                swapMap = new LinkedHashMap<>();
//                swapMap.putAll(contextMap);
//            }
//        }
//    }
//
//    /**
//     * 组装数据, 游标 + 1
//     */
//    private void addData() {
//        // 写入
//        writerHandle(handleData(contextMap));
//        // 每次写入数据 次数都需要 + 1
//        runTimes++;
//        overTime = contextMap.get("timestamp");
//    }
//
//    /**
//     * 去读缓存数据 该处的数据冲临时缓存中获取, 游标 + 1
//     */
//    private void addData(Map<String, String> map) {
//        // 写入
//        writerHandle(handleData(map));
//        // 每次写入数据 次数都需要 + 1
//        runTimes++;
//        overTime = map.get("timestamp");
//    }
//
//    /**
//     * 装载头信息
//     *
//     * @param strings 读取的当前行数据
//     */
//    private void titleHandle(String[] strings) {
//        // 初始化数据存储map的时间戳
//        contextMap.put("timestamp", "0");
//        StringBuilder title = new StringBuilder("timestamp");
//        for (String str : strings) {
//            String[] headTxt = str.split(":");
//            // 头信息存入map 用于后面便利数据
//            titleMap.put(headTxt[1], headTxt[0]);
//            // 装载一个与头信息一样的map 方便后面数据跟头数据的顺序保持一致
//            contextMap.put(headTxt[1], "0");
//            // 组装头信息
//            title.append(";").append(headTxt[1]);
//        }
//        // 写入
//        writerHandle(String.valueOf(title));
//    }
//
//    /**
//     * 将数据中的值（contextMap）与头信息（titleMap）一一对应赋值
//     * 这里的数据 n  覆盖 n-1
//     *
//     * @param strings 读取的当前行数据
//     */
//    private void handleMap(String[] strings) {
//        // 查找当前数据 相对于头数据的属性
//        for (String name : titleMap.keySet()) {
//            if (titleMap.get(name).equals(strings[1])) {
//                contextMap.put(name, strings[2]);
//                // 如果当前时间节点数据组块里面有没有重复编码数据，此处找到数据后可以使用break;提高效率
//                break;
//            }
//        }
//    }
//
//    /**
//     * 将map 中的值 组装成string
//     *
//     * @param map
//     * @return
//     */
//    private String handleData(Map<String, String> map) {
//        // 将上一个timestamp 还原，否则当前时间为n+1行的时间，没有在赋值前做是因为如果数据为最后一行，将少一条数据
//        // 组装写入txt的 string
//        StringBuilder context = new StringBuilder();
//        for (String name : map.keySet()) {
//            // 这里为了删除最后一个；
//            if ("timestamp".equals(name)) {
//                context.append(map.get(name));
//            } else {
//                context.append(";").append(map.get(name));
//            }
//        }
//        return String.valueOf(context);
//    }
//
//    /**
//     * 写入数据  Spring环境上可以考虑使用log日志方式
//     * <p>
//     * 写入数据地址
//     */
//    private BufferedWriter bw;
//
//    {
//        try {
//            bw = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(new File("C://data_input//value_map.txt")), "UTF-8"));
//        } catch (UnsupportedEncodingException e) {
//            e.printStackTrace();
//        } catch (FileNotFoundException e) {
//            e.printStackTrace();
//        }
//    }
//
//    /**
//     * writer data for txt
//     */
//    private void writerHandle(String string) {
//        try {
//            bw.write(string);
//            bw.newLine();
//        } catch (Exception e) {
//            System.err.println("write errors :" + e);
//        }
//    }
//}
